﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
using System.Reflection;

namespace System;


public static class CoreExtension
{
    /// <summary>
    /// 获取当前服务的接口层和实现层
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static Assembly[] GetApplicationServiceAssembly()
    {
        string exeName = AppDomain.CurrentDomain.FriendlyName;
        var strs = exeName.Split('.');
        string startName = $"{strs[0]}.{strs[1]}";

        string path = AppDomain.CurrentDomain.BaseDirectory;
        var files = Directory.GetFiles(path).Select(s => Path.GetFileName(s)).ToArray();
        var appDllList = files.Where(s => s.StartsWith(startName)
            && (s.EndsWith(".Application.dll") || s.EndsWith(".Application.Contracts.dll")))
            .ToArray();
        if (appDllList.Length == 0)
            return new Assembly[0];

        List<Assembly> assemblies = new List<Assembly>(appDllList.Length);
        foreach (string dllName in appDllList)
        {
            var assembly = Assembly.Load(dllName.Replace(".dll", string.Empty));
            if (assembly != null) assemblies.Add(assembly);
        }

        return assemblies.ToArray();
    }

    /// <summary>
    /// 使用自定义路由扩展方法
    /// </summary>
    /// <param name="opts"></param>
    /// <param name="routeAttribute"></param>
    public static void UseCentralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
    {
        opts.Conventions.Insert(0, new RouteConvention(routeAttribute));
    }

}

public class RouteConvention : IApplicationModelConvention
{
    private readonly AttributeRouteModel _routePrefix;

    public RouteConvention(IRouteTemplateProvider routeTemplateProvider)
    {
        _routePrefix = new AttributeRouteModel(routeTemplateProvider);
    }

    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList();
            if (matchedSelectors.Any())
                foreach (var selectorModel in matchedSelectors)
                    selectorModel.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selectorModel.AttributeRouteModel);

            var unmatchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel == null).ToList();
            if (unmatchedSelectors.Any())
                foreach (var selectorModel in unmatchedSelectors)
                    selectorModel.AttributeRouteModel = _routePrefix;
        }
    }

}
